In [1]:
import numpy as np
import cv2
from matplotlib import pyplot as plt
import json
import collections as cl
%matplotlib inline

🐍Jupyter上でインライン表示するための関数を定義

  • 以降、こいつに画像データを渡せばインライン表示してくれる!
  • 読みやすくするためだけの関数
In [2]:
from IPython.display import display, Image

def display_cv_image(image, format='.png'):
    decoded_bytes = cv2.imencode(format, image)[1].tobytes()
    display(Image(data=decoded_bytes))

🐍まず原画像の確認

In [3]:
LoL = cv2.imread('resource/LumpofLeaves.png')
display_cv_image(LoL)

🐍もこもこした塊の部分を抽出したい

  • そのためまずはもこもこした塊の特徴をつかみたいので、適当にもこもこ部分を切り出してみる
  • ペイントで切り出しました
    • crop1 : 2000,2300を左上にして、600,350を切り取った
    • crop2 : 850, 1350を左上にして、300,200を切り取った
    • crop3 : 3250, 1600を左上にして、350,300を切り取った
In [4]:
crop1 = cv2.imread('resource/crop1.png')
display_cv_image(crop1)
In [5]:
crop2 = cv2.imread('resource/crop2.png')
display_cv_image(crop2)
In [6]:
crop3 = cv2.imread('resource/crop3.png')
display_cv_image(crop3)

🐍比較のため関係ないところも

In [7]:
crop4 = cv2.imread('resource/crop4.png')
display_cv_image(crop4)
In [8]:
crop5 = cv2.imread('resource/crop5.png')
display_cv_image(crop5)

🐍とりあえず切り取った画像をHSV色空間に変更してみる

  • こっちのほうがBGR形式よりも直感的にいじれる
  • HSV色空間についての解説はここ。むっちゃわかりやすい
  • もっとカラフルな画像でやってみたのも、hsv_example.htmlにある
  • むしろfor文の内包表記のほうが分かりづらいはず
In [9]:
imgs = [crop1, crop2, crop3, crop4, crop5]
hsv_imgs = [cv2.cvtColor(img, cv2.COLOR_BGR2HSV) for img in imgs]

🐍1つずつHSVのヒストグラムを表示してみる

  • それぞれの値の、平均、分散も表示してみた。
In [10]:
for i, hsv_img in enumerate(hsv_imgs):

    h, s, v = hsv_img[:,:,0], hsv_img[:,:,1], hsv_img[:,:,2]

    h_hist, bins = np.histogram(h.ravel(),256,[0,256], density=True)
    s_hist, bins = np.histogram(s.ravel(),256,[0,256], density=True)
    v_hist, bins = np.histogram(v.ravel(),256,[0,256], density=True)
    
    X = []
    
    for j in range(1, len(bins)):
        X.append((bins[j-1] + bins[j]) / 2)

    fig = plt.subplot()
    
    fig.bar(X, h_hist)
    fig.bar(X, s_hist)
    fig.bar(X, v_hist)
    fig.set_ylim(0,0.15)
    fig.set_aspect(800)
    plt.show()
    
    print('Hue(色相)の        中央値:{} 平均:{} 分散:{}'.format(np.median(h), np.mean(h), np.var(h)))
    print('Saturation(彩度)の 中央値:{} 平均:{} 分散:{}'.format(np.median(s), np.mean(s), np.var(s)))
    print('Value(明度)の      中央値:{} 平均:{} 分散:{}'.format(np.median(v), np.mean(v), np.var(v)))
Hue(色相)の        中央値:10.0 平均:13.421423809523809 分散:491.14148292514733
Saturation(彩度)の 中央値:128.0 平均:140.73820952380953 分散:3599.0482371751473
Value(明度)の      中央値:67.0 平均:80.15007619047618 分散:2884.075743803719
Hue(色相)の        中央値:11.0 平均:13.0341 分散:284.89933719000004
Saturation(彩度)の 中央値:109.0 平均:121.69065 分散:3264.683919244166
Value(明度)の      中央値:51.0 平均:59.146633333333334 分散:1376.9299319988888
Hue(色相)の        中央値:20.0 平均:23.321580952380952 分散:353.0247380720182
Saturation(彩度)の 中央値:85.0 平均:98.9748380952381 分散:3354.2700335452146
Value(明度)の      中央値:44.0 平均:58.19201904761905 分散:1969.1678334472565
Hue(色相)の        中央値:24.0 平均:24.445130169539617 分散:93.70077379485983
Saturation(彩度)の 中央値:120.0 平均:134.67386678016598 分散:3367.105703520026
Value(明度)の      中央値:121.0 平均:123.72004681847201 分散:3636.488803629786
Hue(色相)の        中央値:20.0 平均:24.167093001093424 分散:594.4430741408688
Saturation(彩度)の 中央値:6.0 平均:7.58928446036093 分散:79.49425776340503
Value(明度)の      中央値:229.0 平均:222.87819374642632 分散:615.7352961526175

🐍19/3/26 Hueのヒストグラムのデータをjson形式で出力

In [11]:
for i, hsv_img in enumerate(hsv_imgs):

    h= hsv_img[:,:,0]

    h_hist, bins = np.histogram(h.ravel(),180,[0,180], density=True)
    bins = np.delete(bins, 180, axis = 0)
    
    output = cl.OrderedDict()
    output['index'] = bins.tolist()
    output['hue'] = h_hist.tolist()
    
    filename = 'output_jsons/hue_hist_{num}.json'.format(num = str(i+1))
    
    with open(filename, 'w') as fw:
        json.dump(output, fw, indent=2)
    

🎉ヒストグラムとhsvの代表値を見たところ…🎉

  • Hue(色相)の値が分類の手掛かりになると思っていたけど、灰色のコンクリート(crop5)も、crop1~4と同じような色相を表すってのが予想外だった。
  • Saturation(彩度)が小さければ小さいほど、色が薄くなるため、コンクリートはSaturationに閾値を設けると除外できそう
  • Value(明度)が小さいほど、黒っぽい色になる。今回の目当ての領域はたぶんあまり明度が大きくない領域であるため、Valueも利用できそう。

  • (参考)Hueの表↓

In [12]:
hue = cv2.imread('resource/Hue.png')
display_cv_image(hue)